package com.vv.tools.common.demo;

import com.vv.tools.common.message.CustomerBizException;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import org.apache.hc.core5.net.URIBuilder;
import org.apache.hc.core5.util.Timeout;
import org.springframework.http.HttpMethod;
import org.springframework.web.util.UriComponentsBuilder;

import static com.vv.tools.common.message.ResultEnum.EXCEPTION;


public class HttpPool {

    private CloseableHttpClient client;

    public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException {
        HttpPool httpPool = new HttpPool();
        httpPool.test();
    }

    private void test() {
        String httpMethod = "POST";
        String url = "https://api-pre.zatb.co.th/oauth/token";
        String encode = URLEncoder.encode("5iAjqsjbhbjZgdYHFEXLH3tbx+KLNu4hPRGwHwa8/ypY7RES");
        Object body = "client_id=YWM2NjAyNDEtOTVkNi00NzQ0LTliOWEtMWIzMTE5MDVlMGNmOmJsaW5n" +
                      "&client_secret=" + encode + "&grant_type=client_credentials";
        Map<String, String> header = new HashMap<>();
        header.put("Content-Type", "application/x-www-form-urlencoded");

        String s = doGet(httpMethod, url, header, body);
        System.out.println(s);
    }

    private String doGet(String httpMethod, String url, Map<String, String> headerMap, Object requestBody) {
        CloseableHttpClient httpClient = getHttpClient();
        try {
            ClassicHttpRequest httpUriRequest = toHttpUriRequest(httpMethod, url, headerMap, requestBody);
            return httpClient.execute(httpUriRequest, new BasicHttpClientResponseHandler());
        } catch (URISyntaxException | IOException e) {
            e.printStackTrace();
            throw new CustomerBizException(EXCEPTION);
        }
    }

    private CloseableHttpClient getHttpClient() {

        if (null == client) {
            // 创建请求配置
            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(
                Timeout.ofMilliseconds(30000)).setResponseTimeout(
                Timeout.ofMilliseconds(10000)).build();

            // 创建Socket配置
            SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(Timeout.ofMilliseconds(30000)).build();

            // 创建连接管理器
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
            connectionManager.setMaxTotal(100);
            connectionManager.setDefaultMaxPerRoute(50);
            connectionManager.setDefaultSocketConfig(socketConfig);

            // 创建HttpClientBuilder
            HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager)
                .setConnectionManagerShared(true).setConnectionReuseStrategy(new DefaultConnectionReuseStrategy());

            // 构建HttpClient
            client = builder.build();

        }
        return client;
    }


    private ClassicHttpRequest toHttpUriRequest(String httpMethod, String url, Map<String, String> headerMap, Object requestBody)
        throws URISyntaxException {

        ClassicRequestBuilder requestBuilder = ClassicRequestBuilder.create(httpMethod);

        // 构建url\
        URI uri = new URIBuilder(url.replace(" ", "%20")).build();
        requestBuilder.setUri(uri.getScheme() + "://" + uri.getAuthority() + uri.getRawPath());

        //request query params
        UriComponentsBuilder.fromUri(uri).build().getQueryParams().toSingleValueMap().forEach(requestBuilder::addParameter);

        //request headers
        if (!MapUtils.isEmpty(headerMap)) {
            headerMap.forEach(requestBuilder::addHeader);
        }

        //request entity
        if (!HttpMethod.GET.matches(httpMethod) && null != requestBody) {
            HttpEntity httpEntity;
            Header mimeTypeHeader = requestBuilder.getFirstHeader("Content-Type");
            if (mimeTypeHeader != null) {
                ContentType mimeType = ContentType.create(mimeTypeHeader.getValue()).withCharset(StandardCharsets.UTF_8);
                httpEntity = new StringEntity((String) requestBody, mimeType);
            } else {
                httpEntity = new StringEntity((String) requestBody);
            }
            requestBuilder.setEntity(httpEntity);
        }

        // 构建request
        return requestBuilder.build();
    }


}
